package org.zjx.core;

import lombok.Data;

import java.net.InetSocketAddress;
import java.util.*;

@Data
public class ConfigBasedClusterConfig implements ClusterConfig {
    private final InetSocketAddress masterAddress;
    private Set<InetSocketAddress> slaveNodes;
    private Map<String, InetSocketAddress> commandRouting;

    public ConfigBasedClusterConfig(InetSocketAddress masterAddress,
                                    Map<String, InetSocketAddress> commandRouting) {
        this.masterAddress = masterAddress;
        this.slaveNodes = Set.copyOf(commandRouting.values());
        this.commandRouting = Map.copyOf(commandRouting);
    }


    @Override
    public InetSocketAddress getNodeForCommand(String command) {
        String bestMatch = null;
        for (String key : commandRouting.keySet()) {
            if (command.startsWith(key) && (bestMatch == null || key.length() > bestMatch.length())) {
                bestMatch = key;
            }
        }
        return bestMatch != null ? commandRouting.get(bestMatch) : null;
    }


    @Override
    public void addCommandMapping(String command, InetSocketAddress node) {
        Map<String, InetSocketAddress> newRouting = new HashMap<>(commandRouting);
        newRouting.put(command, node);
        commandRouting = Map.copyOf(newRouting);

        addSlaveNode(node);
    }

    @Override
    public void removeCommandMapping(String command) {
        Map<String, InetSocketAddress> newRouting = new HashMap<>(commandRouting);
        newRouting.remove(command);
        commandRouting = Map.copyOf(newRouting);
    }

    public void addSlaveNode(InetSocketAddress node) {
        if (!slaveNodes.contains(node) && !masterAddress.equals(node)) {
            Set<InetSocketAddress> newNodes = new HashSet<>(slaveNodes);
            newNodes.add(node);
            slaveNodes = Set.copyOf(newNodes);
        }
    }
}
